#ifndef _serialization_wrap_h_
#define _serialization_wrap_h_
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/string.hpp>
#include <fstream>
#include <boost/mpl/logical.hpp>
#include <boost/type_traits/is_same.hpp>
#include "smart_ptr4ObjC.h"



typedef boost::archive::xml_iarchive serialization_iarchive_t;
typedef boost::archive::xml_oarchive serialization_oarchive_t;
//typedef boost::archive::binary_iarchive serialization_iarchive_t;
//typedef boost::archive::binary_oarchive serialization_oarchive_t;

struct CGPoint {
	float x;
	float y;
};
struct CGSize {
	float width;
	float height;
};
struct CGRect {
	CGPoint origin;
	CGSize size;
};

template<class Archive>
void serialize(Archive & ar, CGPoint &obj, const unsigned int version)
{
	ar  & boost::serialization::make_nvp("x", obj.x)
	& boost::serialization::make_nvp("y", obj.y);
}

template<class Archive>
void serialize(Archive & ar, CGSize &obj, const unsigned int version)
{
	ar  & boost::serialization::make_nvp("width", obj.width)
	& boost::serialization::make_nvp("height", obj.height);
}

template<class Archive>
void serialize(Archive & ar, CGRect &obj, const unsigned int version)
{
	ar  & boost::serialization::make_nvp("origin", obj.origin)
	& boost::serialization::make_nvp("size", obj.size);
}

typedef struct {
	CGPoint pos;
	std::string normal;
	std::string selected;
	std::string disable;
	template<class Archive>	
	void serialize(Archive & ar, const unsigned int version)
	{
		ar  & BOOST_SERIALIZATION_NVP(pos);
		ar  & BOOST_SERIALIZATION_NVP(normal);
		ar  & BOOST_SERIALIZATION_NVP(selected);
		ar  & BOOST_SERIALIZATION_NVP(disable);		
	}
}menu_item_info_t;

typedef struct {
	CGPoint pos;
	std::string name;
	template<class Archive>	
	void serialize(Archive & ar, const unsigned int version)
	{
		ar  & BOOST_SERIALIZATION_NVP(pos);
		ar  & BOOST_SERIALIZATION_NVP(name);	
	}
}image_info_t;

template <typename  T>
inline void setPosition(T *ptr, CCPoint pos)
{
	ptr->setPosition(pos);
}

template <typename  T>
inline void setPosition(T *ptr, const CGPoint & pos)
{
	setPosition(ptr, CCPoint(pos.x, pos.y));
}

template <bool> struct ccpoint_add_imp {
	template <typename T1, typename T2>
	static inline CCPoint add(T1 &a, T2 &b) {
		return CCPoint(a.x+b.x, a.y+b.y);
	}
};

template <> struct ccpoint_add_imp<false> {
	template <typename T1, typename T2>
	static inline CCPoint add(T1 &a, T2 &b) {
		return CCPoint(a.x+b.width, a.y+b.height);
	}
};


template <typename T1, typename T2>
inline CCPoint operator+(T1 &a, T2 &b)
{
	return ccpoint_add_imp< boost::mpl::or_<boost::is_same<T1, CCPoint>, boost::is_same<T1, CGPoint> >::value>::add(a, b);
}



inline CCMenuItemImage *getMenuItem(const menu_item_info_t &info, SelectorProtocol* p, SEL_MenuHandler s)
{
	CCMenuItemImage *ret = CCMenuItemImage::itemFromNormalImage(info.normal.c_str(), info.selected.c_str(), info.disable.c_str(),
																p, s);
	setPosition(ret, info.pos);
	return ret;
}

inline void setImage(scoped_object_c_ptr<CCSprite> &image, const image_info_t &info)
{

	if (NULL == image.get()) {		
		image.reset(CCSprite::spriteWithFile(info.name.c_str()));
		image->retain();
	}
	setPosition(image.get(), info.pos);
}



#endif